import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/*
 * En este ejercicio, se ha usado el ejercicio 24 como un método dentro del propio
 * ejercicio 25 que se llama operacion, ese metodo devuelve la operación resultado
 * de una expresión en un String. Para resolver el ejercicio, se le mandará al
 * método "operación" cada uno de los paréntesis para que evalúe sus operaciones de
 * dentro.
 */

public class ej25 {

//	Métodos a utilizar
	public static float potencia(float base, float exponente){ /* Función potencia para realizar potencias de
			* distintas bases de forma fácil.*/
		float resultado=1;
		int i;
		for(i=1;i<=exponente;i++)
			resultado=resultado*base;

		return resultado;
	}
	
	/*
	 * Para tratar este ejercicio, a la hora de realizar los operadores, realizaré
	 * distintas funciones para cada una de ellas, y se ejecutarán en orden de
	 * preferencia para que se mantengan correctamente las preferencias, 
	 * dichas preferencias son en orden de importancia:
	 * Potencias, Multiplicación/División, Suma/Resta
	 * Después de Realizar cada operación, reordenaré el vector que contiene a los
	 * operadores y los números, para ir dejando las zonas vacías al final del vector
	 * y mostraré la operación que quedaría por evaluar en la siguiente operación
	 * según el orden de preferencia
	 */

	
	public static String operacion (String entrada) {
		//Constantes, tamaño de los arrays referidos a operadores y números
		final int operadores_totales = 100;
		final int numeros_totales = 100;
		
		//Variables
		int i,j,k; //Iteradores
		int n_op = 0;//contador de operadores
		int n_num = 0; //contador de numeros
		float numero[] = new float [numeros_totales];//Almacena los números con los que se opera
		char op[] = new char[operadores_totales]; //almacena los operadores por orden
		char entradaC[];//Almacena las componentes del String de Entrada
		
		String[] numeroS = new String [numeros_totales]; //Strings donde se almacenarán los números leidos
														 // poco a poco de la cadena de carácteres.
		String resultado;

		//Convierto el String en un ARRAY de carácteres
		entradaC = new char [entrada.length()];
		for(i=0;i<entrada.length();i++)
			entradaC[i] = entrada.charAt(i);
		

		//Recorre el Array buscando los operadores y almacenándolos en orden.
		for(i=0;i<entrada.length();i++){
			//si se encuentra un operador
			if(entradaC[i]=='/'||entradaC[i]=='-'||entradaC[i]=='+'){
				op[n_op] = entradaC[i]; //pasa el símbolo al vector de operadores
				n_op++; //avanza una posición en el vector
			}
			else if(entradaC[i]=='*'){ //Trata a la multiplicación como caso aparte
				if (entradaC[i+1]=='*'){
					op[n_op] = '^'; //si hay dos * seguidos, almacena la potencia
					n_op++;	// y avanza lugar en el operador
					i++; //Se salta un lugar en el iterador, puesto que el siguiente también va a ser *
				}
				else {
					op[n_op] = '*'; //sino es una potencia, sino un *, actúa como en los demas casos
					n_op++;
				}
			}
		}
	
		//ANTES de manejar el Array de strings, inicializo todos
		//sus valores a "" (nada), para evitar posteriores errores "null"
		for(i=0;i<=9;i++)
			numeroS[i]= "";

		
		//Recorre el Array buscando los números y almacenándolos en orden.
		for(i=0;i<entrada.length();i++){
			if(entradaC[i]=='/'||entradaC[i]=='-'||entradaC[i]=='+'){
				//Si llega hasta un operador, se lo salta y avanza al siguiente número
				// del array de Strings
				n_num++;
			}
			else if(entradaC[i]=='*'){ //ahora hay que tener en cuenta el **, si encuentra un * evalúa si se
									// tiene que saltar 1 o dos posiciones
			
				if(entradaC[i+1]=='*'||entradaC[i]=='/'||entradaC[i]=='-'||entradaC[i]=='+'){
							//si hay otro símbolo adicional, avanza posiciones adicionales
					i++;
					n_num++;
				}
				else n_num++;
				
			}
			
			else numeroS[n_num]+=String.valueOf(entradaC[i]);
		}
		//Transforma los strings de números a un vector de enteros
		for(i=0;i<=n_num;i++){
			if (numeroS[i]!="") //evita que intente evaluar Strings de números vacíos
				numero[i] = Float.parseFloat(numeroS[i]);
		}
		
		/*Una vez con los números puestos en el array numero[] de tamaño n_num
		y con los operadores en op[] de tamaño n_op, A DIFERENCIA DE EJERCICIOS
		ANTERIORES, se harán tantas funciones como operaciones hayan, almacenando
		los sucesivos resultados en en mismo array que será reordenado tras cada
		ejecución de las operaciones.
		
		
			Apartado de POTENCIAS.
		 
		  Va revisando los operadores, cuando encuentra una potencia, eleva al exponente
		  al número que acompaña
		 */
	
		
		for (i=0,j=0;i<=n_op;){ //Realiza las potencias que encuentre y las almacena en el mismo vector
			if(op[i]=='^'){
				numero[i] = potencia(numero[i],numero[i+1]);
				op[i]='0'; //Asigna 0 al operador ya usado, para luego al reordenar colocarlo al final
				numero[i+1]=0;
			}
			else i++;/*	sólo aumenta el iterador (pasa a la siguiente posición del signo) si no realiza la operación
					 	puesto que en caso de hacerla, al reordenar, el operador que habrá que evaluar ocupará esta
						misma posición.*/
			
			for(k=0;k<=n_num;k++)        //Estos "for" reordena los operadores y los números, tiene que ser después
				for(j=0;j<=n_num;j++){   //de realizar cada operación, dentro del for, puesto que si se hace fuera
					if(numero[j]==0){	 //no se podrían encadenar varias operaciones del mismo tipo.
						numero[j]=numero[j+1];
						numero [j+1]=0;
					}
				} 
			
			for(k=0;k<=n_num;k++)
				for(j=0;j<=n_num;j++){
					if(op[j]=='0'){
						op[j]=op[j+1];
						op[j+1]='0';
					}
				}
			
		}		
		//FIN APARTADO POTENCIAS
		
		//FUNCIÓN MULTIPLICACIÓN Y DIVISIÓN
		for (i=0;i<=n_op;){ //Realiza las MULT/DIV que encuentre y las almacena en el mismo vector
			if(op[i]=='*'){
				numero[i] = numero[i]*numero[i+1]; //realiza la operación correspondiente y lo almacena en el 1º num
				op[i]='0'; //Asigna 0 al operador ya usado, para luego al reordenar colocarlo al final
				numero[i+1]=0; //Lo mismo con el número de después del operador
			}
			else if(op[i]=='/'){
				numero[i]= numero[i]/numero[i+1];
				op[i]='0';
				numero[i+1]=0;
			}
			else 
				i++;
				
			for(k=0;k<=n_num;k++)        //Estos "for" reordena los operadores y los números, tiene que ser después
				for(j=0;j<=n_num;j++){   //de realizar cada operación, dentro del for, puesto que si se hace fuera
					if(numero[j]==0){	 //no se podrían encadenar varias operaciones del mismo tipo.
						numero[j]=numero[j+1];
						numero [j+1]=0;
					}
				} 
			
			for(k=0;k<=n_num;k++)
				for(j=0;j<=n_num;j++){
					if(op[j]=='0'){
						op[j]=op[j+1];
						op[j+1]='0';
					}
				}
			 
		}
		//FIN APARTADO MULTIPLICACIONES Y DIVISIONES
	
//		FUNCIÓN SUMA Y RESTA
		for (i=0;i<=n_op;i++){ //Realiza las SUMAS/RESTAS que encuentre y las almacena en el mismo vector
			if(op[0]=='+'){
				numero[0] = numero[0]+numero[1]; //realiza la operación correspondiente y lo almacena en el 1º num
				op[0]='0'; //Asigna 0 al operador ya usado, para luego al reordenar colocarlo al final
				numero[i+1]=0; //Lo mismo con el número de después del operador
			}
			if(op[0]=='-'){
				numero[0]= numero[0]-numero[1];
				op[0]='0';
				numero[1]=0;
			}
				
			for(k=0;k<=n_num;k++)        //Estos "for" reordena los operadores y los números, tiene que ser después
				for(j=0;j<=n_num;j++){   //de realizar cada operación, dentro del for, puesto que si se hace fuera
					if(numero[j]==0){	 //no se podrían encadenar varias operaciones del mismo tipo.
						numero[j]=numero[j+1];
						numero [j+1]=0;
					}
				} 
			
			for(k=0;k<=n_num;k++)
				for(j=0;j<=n_num;j++){
					if(op[j]=='0'){
						op[j]=op[j+1];
						op[j+1]='0';
					}
				}
			 
		}
		//FIN APARTADO SUMAS Y RESTAS
		
		
		//DEVUELVE EL RESULTADO FINAL
		resultado = ""+(int)numero[0]; //Paso el float a un Int (para quitar el decimal) Y LO METO en un String que devolverá la función
		return resultado;
	}
	
	
	
//FINAL DE LOS MÉTODOS A UTILIZAR EN MAIN.	
	
	
	public static void main(String[] args) throws IOException{
		
		int i,j; //iteradores
		int par1,par2; //posiciones de los paréntesis
		boolean cerrado=false; //dice cuando se ha cerrado un paréntesis.
		int ptotales=0; //cantidad de paréntesis totales
		
		String entrada;//String donde se almacenará lo introducido por teclado
		
		InputStreamReader teclado; //Declaro la entrada de datos
		BufferedReader bufferLectura;//Declaro Buffer de entrada

		
		teclado = new InputStreamReader (System.in);//Paso al InputStreamReader la entrada de teclado 
		bufferLectura = new BufferedReader (teclado);//Se almacena en el buffer
		
		System.out.println("\tOPERACIONES POSIBLES (Entre paréntesis su PREFERENCIA)\n- Suma:\t\t\t \"+\"(3)\n- Resta:\t\t \"-\"(3)\n- Multiplicación:\t \"*\"(2)\n- División:\t\t \"/\"(2)\n- Potencia:\t\t \"**\"(1) (después debe ponerse el exponente)\n\tEj. 3³ + 5 = 3**3+5\n\tNota: Se pueden utilizar paréntesis para afectar el orden en el que se evalúan las operaciones)\n");
		System.out.print("Introduce la operación: ");
		entrada = bufferLectura.readLine(); //Paso al String la línea introducida a través del Buffer
		//Cuenta los paréntesis de entrada
		for(i=0;i<entrada.length();i++)
			if (entrada.charAt(i)=='(')
				ptotales++;
		
		
		
		/*DETECTA EL PARÉNTESIS DE ENTRADA MAS PEQUEÑO DISPONIBLE
		 * es decir, sólo tiene en cuenta el paréntesis
		 * si lo ante de encontrar otro paréntesis abierto, 
		 * encuentra uno cerrado, por lo que dentro de
		 * dicho paréntesis no habrá ningún otro.
		 * en ese caso, marca como substring a analizar lo que
		 * va entre las posiciones de ambos paréntesis
		 */
		
		//En caso de no haber paréntesis, tomará los valores por defecto siguientes
		//a la hora de analizar el substring.
				par1=0;
		par2=entrada.length();
		
		j=0;
		do{
		i=0;//inicia el iterador para el do-while
		do{
			if(entrada.charAt(i)=='(') //si encuentra un paréntesis
				par1=i+1; //apunta la posición siguiente al paréntesis para posteriormente hacer un substring empezando en dicha posición
			else if(entrada.charAt(i)==')'){
				par2=i;//En el caso del paréntesis de cierre, toma la posición simplemente para que tenga en cuenta también el último numero
				cerrado=true;
			}
			i++;
		}
		while (i<entrada.length()&&cerrado==false);
		cerrado=false;//devuelve el valor por defecto para poder usarlo la siguiente vez
		/* Una vez determinada la dimensión del substring correspondiente al
		 * paréntesis, lo evalúa con el método operacion. En el mismo string entrada,
		 * concatena el resultado a lo que había antes del paréntesis, y a
		 * continuación pone lo que había despues del paréntesis, de éste modo
		 * el paréntesis queda sustituido por su valor en el string entrada.
		 * Por lo que cada vez que se resuelva un paréntesis, la entrada cambiará
		 * y el lugar del paréntesis lo ocupará su expresión.
		 */
		entrada = entrada.substring(0,par1-1) + operacion(entrada.substring(par1,par2)) + entrada.substring(par2+1);
			
		
		System.out.println("\t-Operando... "+entrada);
		j++;
		}
		while(j<ptotales);
		
		//Cuando termina de resolver los paréntesis, tendremos una expresión que será tratable con
		//el método operacion de forma normal, por lo que lo tratamos normalmente

		System.out.print("\n\n\t RESULTADO: "+operacion(entrada));
	}

}
